package cn.mw.cmdb.processor;

import cn.mw.cmdb.entity.*;
import cn.mw.cmdb.param.InstanceSearchParam;
import cn.mw.cmdb.param.TableSearchParam;
import cn.mw.cmdb.service.impl.*;
import cn.mw.cmdb.util.CMDBTool;
import cn.mw.cmdb.viewProcessor.RelateDataViewProcessor;
import cn.mw.cmdb.viewProcessor.ViewProcessorManage;
import cn.mw.microMonitorCommon.api.common.Constants;
import cn.mw.microMonitorCommon.entity.cmdb.RelatedDataType;
import cn.mw.microMonitorCommon.entity.cmdb.TableHeaderItem;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

import static cn.mw.cmdb.processor.TableDataFactory.createTableHeaderId;
import static cn.mw.microMonitorCommon.entity.cmdb.TableHeaderItem.flexNum;

/**
 * 模型列表通用Processor
 */
public class StaticsProcessorCustom implements TableDataProccessor {
    private CmdbServiceManage cmdbServiceManage;

    private TableSearchParam tableDataParam;


    private CustomClassificationVo customClassificationVo;

    public StaticsProcessorCustom(CmdbServiceManage cmdbServiceManage, TableSearchParam tableDataParam) {
        this.cmdbServiceManage = cmdbServiceManage;
        this.tableDataParam = tableDataParam;
        CustomClassificationServiceImpl customClassificationService = (CustomClassificationServiceImpl) cmdbServiceManage.getModelService(CustomClassificationServiceImpl.ID);
        customClassificationVo = customClassificationService.doSelectById(tableDataParam.getTableId());
    }


    @Override
    public List genData(TableDataProcessorContext context) throws Exception {
        List<Map> ret = new ArrayList<>();
        if (customClassificationVo == null) {
            return ret;
        }
        List<Map> listMap = new ArrayList<>();
        CustomModelServiceImpl customModelService = (CustomModelServiceImpl) cmdbServiceManage.getModelService(CustomModelServiceImpl.ID);
        // 查询数据范围内的所有名称
        List<ModelInfo> modelInfos = customModelService.selectByTreeViewList(customClassificationVo.getTreeViewList());
        if (null != modelInfos && modelInfos.size() > 0) {
            List<String> modelIds = modelInfos.stream().map(ModelInfo::getId).toList();
            InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
            InstanceSearchParam instanceSearchParam = new InstanceSearchParam();
            instanceSearchParam.setModelIds(modelIds);
            if(tableDataParam.isEnableMonitorStatus()){
                //查询资产状态
                instanceSearchParam.setEnableMonitorStatus(true);
            }
            instanceSearchParam.setEnableMonitorStatus(true);
            if (StringUtils.isNotBlank(tableDataParam.getId())) {
                // 自定义分类场景，状态节点 id由上级id+资产状态组成 id由属性名:属性值拼接而成
                String[] propertyKey2ValueArr = tableDataParam.getId().split(Constants.ID_SPLIT);
                Map<String, Object> key2ValueMap = new HashMap<>();
                String[] key2ValueArr;
                for (String key2ValueStr : propertyKey2ValueArr) {
                    if (key2ValueStr.contains(Constants.PROPERTY_SPLIT)) {
                        key2ValueArr = key2ValueStr.split(Constants.PROPERTY_SPLIT);
                        if (key2ValueArr.length > 1) {
                            key2ValueMap.put(key2ValueArr[0], StringUtils.equals(key2ValueArr[1], Constants.UNKNOWN) ? null : key2ValueArr[1]);
                        } else {
                            key2ValueMap.put(key2ValueArr[0], null);
                        }
                    }
                }
                instanceSearchParam.setData(key2ValueMap);
            }
            //不分页查询,为了排序
            //instanceSearchParam.setPage(null);
            List<InstanceInfoExtend> instanceInfos = instanceService.aggregateList(instanceSearchParam);
            ViewProcessorManage processorManage = new ViewProcessorManage();
            List<TableHeaderItem> tableHeaderItems = context.getTableHeaderItems();
            if (null != instanceInfos && null != tableHeaderItems) {
                Set<RelateDataViewProcessor> relateDataViewProcess = processorManage.buildRelateDataViewProcessor(tableHeaderItems);
                Map<? extends Class<? extends RelateDataViewProcessor>, List<RelateDataViewProcessor>> collect = relateDataViewProcess.stream().collect(Collectors.groupingBy(s -> s.getClass()));
                Set<RelateDataViewProcessor> relateDataViewProcessors = new HashSet<>();
                collect.forEach((k,v)->{
                    if(v!=null && v.size()>0){
                        RelateDataViewProcessor relateDataViewProcessor = v.get(0);
                        relateDataViewProcessors.add(relateDataViewProcessor);
                    }
                });//初始化
                int seq = 0;
                for (InstanceInfoExtend instanceInfo : instanceInfos) {
                    seq++;
                    Map data = new LinkedHashMap();
                    if (tableDataParam.isShowAllField()) {
                        Map<String, Object> dataMap = instanceInfo.getData();
                        data.putAll(dataMap);
                    }
                    for (TableHeaderItem item : tableHeaderItems) {
                        Object value = instanceInfo.getValue(item.getField());
                        data.put(item.getField(), value);
                    }
                    data.put(CMDBTool.getFieldName(InstanceInfoExtend::getModelName),instanceInfo.getModelName());
                    data.put(CMDBTool.getFieldName(InstanceInfoExtend::getModelGroupName), instanceInfo.getModelGroupName());
                    data.put(CMDBTool.getFieldName(InstanceInfoExtend::getModelId), instanceInfo.getModelId());
                    data.put(CMDBTool.getFieldName(InstanceInfoExtend::getFinanceParentId), instanceInfo.getFinanceParentId());
                    data.put(CMDBTool.getFieldName(InstanceInfoExtend::getGroupId), instanceInfo.getGroupId());ret.add(data);
                    //data.put(SEQ, seq);

                    if (null == relateDataViewProcessors || relateDataViewProcessors.size() == 0) {
                        continue;
                    }
                    for (RelateDataViewProcessor processor : relateDataViewProcessors) {
                        processor.init(instanceInfo, data);
                    }
                }

                if (null == relateDataViewProcessors || relateDataViewProcessors.size() == 0) {
                    return ret;
                }
                //查询关联数据
                for (RelateDataViewProcessor processor : relateDataViewProcessors) {
                    processor.selectRelateData(context);
                }

                //设置关联数据
                for (Map s : ret) {
                    for (RelateDataViewProcessor processor : relateDataViewProcessors) {
                        processor.setRelateData(s);
                    }
                }
            }
        }
        return ret;
    }

    @Override
    public List<TableHeaderItem> genDefaultTableHeader(Class clazz) throws Exception {
        List<TableHeaderItem> tableHeaderItems = new ArrayList<>();
        if (customClassificationVo == null) {
            return tableHeaderItems;
        }
        //获取模型自定义的属性
        //根据modelId获取当前模型所对应的全部属性
        //将属性按照显示权限过滤（勾选列表显示的），转换为List<TableHeaderItem>放回
        ModelPropertyServiceImpl modelPropertyService = (ModelPropertyServiceImpl) cmdbServiceManage.getModelService(ModelPropertyServiceImpl.ID);
        List<PropertyInfo> propertyInfos = modelPropertyService.listCommonProperty(customClassificationVo.getTreeViewList());
        //按照属性信息来循环处理,保证只会输入模型中定义的属性
        for (PropertyInfo propertyInfo : propertyInfos) {
            Set<FieldViewAuthType> fieldViewAuthTypes = propertyInfo.getFieldViewAuthTypes();
            //获取所有列表显示的字段属性
            if (null != fieldViewAuthTypes && fieldViewAuthTypes.contains(FieldViewAuthType.list)) {
                TableHeaderItem item = new TableHeaderItem();
                ForeignKey foreignKey = propertyInfo.getForeignKey();
                if (null == foreignKey || !org.springframework.util.StringUtils.hasText(foreignKey.getKeyName())) {
                    item = new TableHeaderItem();
                } else {
                    RelatedDataType relatedDataType = RelatedDataType.valueOf(foreignKey.getRelatedDataType());
                    item = TableHeaderItemExt.build().keyName(foreignKey.getKeyName());
                    item.setParseType(relatedDataType);
                }
                item.setField(propertyInfo.getId());
                item.setPropertyTypeId(propertyInfo.getPropertyTypeRef().getTypeId());
                item.setHeaderName(propertyInfo.getName());
                item.setVisible(true);
                item.setFlex(flexNum);
                if (!tableHeaderItems.contains(item)) {
                    tableHeaderItems.add(item);
                }

            }
        }
        createTableHeaderId(tableHeaderItems);
        return tableHeaderItems;
    }
}
